package client;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import commons.Message;
import commons.OMGProtocol;

/**
 * This is the main client class. This class manages the data transfer 
 * between server and client for the client side. Tasks of this class:
   1.	Takes message from OMCProtocolForClient class and sends to server
   2.	Receives messages from server and delegates to OMCProtocolForClient.java class. 

 */

class OMGPClient {

	private static final int PORT = 4171;
	private Socket socket;
	private DataInputStream in;
	private DataOutputStream out;
	String servername="";

	public OMGPClient(){
		try {
			// Connect
			BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
			while(servername.length()<4 || servername.length()>16)
			{
			  System.out.println("Server: Please enter server's IP address: ");
			  try {
				servername = userInput.readLine();
				
			   } 
			   catch (IOException e) 
			   {
				  System.err.println(" Exception in reading server's IP->"+e.getMessage());
				  
			    }
			
			   
			}
		
				socket = new Socket(servername, PORT);
				out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
				in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

				// Instantiate protocol
				OMGProtocolForClient oProtocol = new OMGProtocolForClient(servername);
				
				// Send authentication request by starting DFA
				Message messageToSend = null;
				Message currentServerMessage = new Message();
				int pastState = -1;
				do {		
					if(oProtocol.getState() != pastState) {
						System.err.println("Client is in state: " + oProtocol.getStateDescription());
						pastState = oProtocol.getState();
					}

					// Get the next message if there is one
					if(in.available() > 0 && currentServerMessage.isRead()) {
						currentServerMessage = new Message(in);
						System.err.println("Message received: " + currentServerMessage.getMessageDescription());
					}


					// Run the DFA
					try {
						messageToSend = oProtocol.runDFA(currentServerMessage);
					} catch (ClassNotFoundException e) {
						System.err.println(" Protocol class is not found->"+e.getMessage());
					}

					// Check if there's a message to send
					if(messageToSend != null) { 
						
						messageToSend.send(out);
					}				
					
				}while (oProtocol.getState() != OMGProtocol.NONE);


				socket.close();
				in.close();
				out.close();
			} catch (UnknownHostException e) {
				System.err.println("Unable to connect, Server is unknown->"+e.getMessage());
				
			} 
			catch (SocketException e1) {
				System.err.println(" exception->"+e1.getMessage());
			}catch (IOException e) {
				System.err.println(" IOException in creating connection->"+e.getMessage());
				  
			}
						
			

	}


	public static void main(String args[]) {
		new OMGPClient();
	}
}
